/* 
 * File:   sphere.cpp
 * Author: chaterolas
 * 
 * Created on 24 de junio de 2009, 08:21 PM
 */

#include "sphere.h"

#define MAX(a,b) (a < b) ? b : a
#define MIN(a,b) (a < b) ? a : b

/**
 * Crea una instancia de de primitivo de esfera apartir de si nombre, material
 * centro y radio.
 * @param material (material del cual esta constituido la esfera)
 * @param (cx, cy, cz) (vector que representa el centro de la esfera)
 * @param radius (radio de la esfera)
 */
Sphere::Sphere(Material* material, double cx, double cy, double cz, double radius) {
    this->radius = radius;
    this->material = material;
    center = new Vector3D(cx, cy, cz);
    light = 0;
}

/**
 * Destruye una instancia de ets eprimitivo junto con sus componentespertinentes
 */
Sphere::~Sphere() {
    delete material;
    delete center;
}

Vector3D *Sphere::getNormal(Vector3D &pos) {
    Vector3D *temp = pos - *center;
    temp->normalize();

    return temp;
}

int Sphere::getType() {
    return SPHERE;
}

double Sphere::intersect(Ray* r) {

    Vector3D *x = *r->getOrigin() - *center;
    Vector3D *rdir = new Vector3D(*r->getDirection());

    double b = 2.0*(x->dot(*rdir));
    double c = x->dot(*x) - radius*radius;
    double disc = b*b - 4*c;

    delete x;
    delete rdir;

    if(disc < 0)
        return INFINITY;

     disc = sqrt(disc);
     double x1 = (disc*(-1.0) - b) / 2.0;
     double x2 = (disc - b) / 2.0;

     if(x1 < 0.0f && x2 < 0.0f){
        return INFINITY;
     }
     if(x1 > 0.0f && x2 > 0.0f){
        return MIN(x1, x2);
     } else {
        return MAX(x2, x1);
     }
}

